#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <assert.h>

enum led_name {
	GREEN = 1,
	YELLOW = 2,
	RED = 3,
};

enum led_brightness {
	LED_OFF = 0,
	LED_ON = 1,
};

enum led_trigger {
    TIMER = 0,
    HEARTBEAT = 1,
    CPU0 = 2,
    CPU1 = 3,
    NONE = 4,
};

int xy_configure_trigger(enum led_name name, enum led_trigger trigger)
{
    FILE *fp;

    assert(trigger == TIMER     ||
           trigger == HEARTBEAT ||
           trigger == CPU0      ||
           trigger == CPU1      ||
           trigger == NONE);
    assert(name == GREEN  ||
           name == YELLOW ||
           name == RED);

    switch (name) {
    case GREEN:
        fp = fopen("/sys/class/leds/green/trigger", "w");
        break;
    case YELLOW:
        fp = fopen("/sys/class/leds/yellow/trigger", "w");
        break;
    case RED:
        fp = fopen("/sys/class/leds/red/trigger", "w");
        break;
    default:
        printf("error: not trigger mode\n");
        break;
    }

    if (NULL == fp) {
        printf("error: can't open the trigger file.\n");
    }

    switch (trigger) {
    case TIMER:
        fputs("timer", fp); 
        break;
    case HEARTBEAT:
        fputs("heartbeat", fp);
        break;
    case CPU0:
        fputs("cpu0", fp);
        break;
    case CPU1:
        fputs("cpu1", fp);
        break;
    case NONE:
        fputs("none", fp);
        break;
    default:
        printf("error: not trigger mode.\n");
        break;
    }

    fclose(fp);

    return 0;
}

int xy_trigger_timer_delay(enum led_name name, 
                           unsigned int delay_on, unsigned int delay_off)
{
    FILE *on, *off;
    char str[32] = {0};

    assert(name == GREEN  ||
           name == YELLOW ||
           name == RED);

    switch (name) {
    case GREEN:
        on = fopen("/sys/class/leds/green/delay_on","w");
        off = fopen("/sys/class/leds/green/delay_off","w");
        break;
    case YELLOW:
        on = fopen("/sys/class/leds/yellow/delay_on","w");
        off = fopen("/sys/class/leds/yellow/delay_off","w");
        break;
    case RED:
        on = fopen("/sys/class/leds/red/delay_on","w");
        off = fopen("/sys/class/leds/red/delay_off","w");
        break;
    default:
        printf("error: no target led!\n");
        break;
	}

    if (NULL == on || NULL == off) {
        printf("error: delay file open fail.\n");
        exit(0);
    }
    
    memset(str, 0, sizeof(str));
    sprintf(str, "%d", delay_on);
    fputs(str, on);

    memset(str, 0, sizeof(str));
    sprintf(str, "%d", delay_off);
    fputs(str, off);

    return 0;
}

int xy_trigger_mode_none(enum led_name name)
{
    xy_configure_trigger(name, NONE);
    return 0;
}

int xy_trigger_mode_heartbeat(enum led_name name)
{
    xy_configure_trigger(name, HEARTBEAT);
    return 0;
}

int xy_trigger_mode_cpu0(enum led_name name)
{
    xy_configure_trigger(name, CPU0);
    return 0;
}

int xy_trigger_mode_cpu1(enum led_name name)
{
    xy_configure_trigger(name, CPU1);
    return 0;
}

int xy_trigger_mode_timer(enum led_name name, 
                          unsigned int on, 
                          unsigned int off)
{
    xy_configure_trigger(name, TIMER);
    xy_trigger_timer_delay(name, on, off);

    return 0;
}

int xy_led_fast_flash(enum led_name name)
{
    xy_trigger_mode_timer(name, 50, 50);
    return 0;
}

int xy_led_slow_flash(enum led_name name)
{
    xy_trigger_mode_timer(name, 1000, 1000);
    return 0;
}

int xy_led_brightness(enum led_name name, enum led_brightness brightness)
{
	FILE *fp;

	assert(name == GREEN  ||
           name == YELLOW ||
           name == RED);
    assert(brightness == LED_OFF || 
           brightness == LED_ON);
    
	switch (name) {
    case GREEN:
        fp = fopen("/sys/class/leds/green/brightness","w");
        break;
    case YELLOW:
        fp = fopen("/sys/class/leds/yellow/brightness","w");
        break;
    case RED:
        fp = fopen("/sys/class/leds/red/brightness","w");
        break;
    default:
        printf("error: no target led!\n");
        break;
	}

	if(fp == NULL) {
		printf("error: cant open the file\n");
		exit(0);
	}

	if(brightness == LED_ON){
		fputc('1',fp);
	}else if(brightness == LED_OFF){
		fputc('0',fp);
	}

	fclose(fp);

	return 0;
}

int xy_led_poweroff()
{
    xy_led_brightness(GREEN, LED_OFF);
    xy_led_brightness(YELLOW, LED_OFF);
    xy_led_brightness(RED, LED_OFF);
    return 0;
}

void main()
{
    xy_led_brightness(GREEN, LED_ON);
    xy_led_brightness(YELLOW, LED_ON);
    xy_led_brightness(RED, LED_ON);
    
    xy_configure_trigger(GREEN, TIMER);
    xy_trigger_timer_delay(GREEN, 100, 100);
}

